#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define Status int
#define OK 0
#define ERROR 1

// 定义联系人分类枚举
typedef enum {
	FAMILY,      // 家人
	FRIEND,      // 朋友
	COLLEAGUE,   // 同事
	CLASSMATE,   // 同学
	OTHER        // 其他
} Category;

typedef struct {
	char name[100];              // 姓名
	char organization[100];     // 单位
	char landline[20];          // 固定电话
	char mobile[20];            // 移动手机
	Category category;   // 分类
	char email[50];             // 电子邮箱
	char qq[15];                // QQ号码
	char address[200];          // 住址
} Contact;

struct {
	Contact persons[1000];
	int count;
} Contacts;

char CategoryTags[5][20] = {"家人", "朋友", "同事", "同学", "其他"};


// 用于判断文件是否存在
int file_exists(const char *filename) {
	FILE *file = fopen(filename, "r");
	if (file) {
		fclose(file); // 记得关闭文件
		return 1;     // 文件存在
	}
	return 0;         // 文件不存在
}

// 从 contacts.csv 文件中读取联系人
// while 类似于 c = getchar()
// 初始化一个结构体
// 如果是 , 就加入一个字段
// 如果遇到 \n 就重复步骤
Status read() {
	FILE *file = fopen("contacts.csv", "r");
	if (!file) {
		printf("Error: 不能打开文件！\n");
		return ERROR;
	}

	Contact *temp_person = malloc(sizeof(Contact));
	if (!temp_person) {
		printf("Error: 内存分配失败！\n");
		fclose(file);
		return ERROR;
	}

	int field_index = 0;
	char string[200];
	int string_length = 0;
	int ch;  // fgetc 返回 int

	while ((ch = fgetc(file)) != EOF) {
		if (ch == ',' || ch == '\n') {
			string[string_length] = '\0';  // 正确终止

			switch (field_index) {
				case 0:
					strcpy(temp_person->name, string);
					break;
				case 1:
					strcpy(temp_person->organization, string);
					break;
				case 2:
					strcpy(temp_person->landline, string);
					break;
				case 3:
					strcpy(temp_person->mobile, string);
					break;
				case 4:
					temp_person->category = string[0] - '0';
					break;
				case 5:
					strcpy(temp_person->email, string);
					break;
				case 6:
					strcpy(temp_person->qq, string);
					break;
				case 7:
					strcpy(temp_person->address, string);
					break;
			}

			string_length = 0;
			field_index++;

			if (ch == '\n') {
				if (field_index != 8) continue;
				Contacts.persons[Contacts.count++] = *temp_person;
				temp_person = malloc(sizeof(Contact));
				field_index = 0;
			}




		} else if (ch != '\r' && ch != '\n' && ch != ',') {
			if (string_length < 199) {  // 防止溢出
				string[string_length++] = ch;
			}
		}
	}

	free(temp_person);  // 释放最后未处理的内存
	fclose(file);
	return OK;
}

// 该函数输出一个人
void _display_contact(int index, Contact Person) {
	printf("编号ID：%d\n", index);
	printf("姓名：%s （%s）\n", Person.name, Person.organization);
	printf("固定电话：%s  移动手机：%s\n", Person.landline, Person.mobile);
	printf("分类标签：%s\n", CategoryTags[Person.category]);
	printf("电子邮箱：%s\n", Person.email);
	printf("QQ：%s\n", Person.qq);
	printf("地址：%s\n", Person.address);
	printf("==============================================\n");
}

// 展示 contacts 中所有的联系人
// 如果 index == -1 ，切屏显示模式，每页显示10条，
// 1...
// 2..
// ...
// .....
// 按回车进入下一页，输入数字跳转跳转指定页
// 输入 0 退出
Status display(int index) {
	/*
		函数说明：当 index == -1 时进入交互，用户可以查看所有联系人分页
				  当 index >= 0 时，输出指定 index 的联系人

	*/

	// 输出所有联系人（分页）
	if (index == -1) {
		int page = 0;   // 目前页码

		// 输出前 10 页
		printf("==============================================\n");

		for (int i = 0; i < page + 10 && i < Contacts.count; i++) {
			_display_contact(i, Contacts.persons[i]);
		}


		// 计算一共有多少页
		int total_page;
		if (Contacts.count % 10 != 0) {
			total_page = Contacts.count / 10 + 1;
		} else {
			total_page = Contacts.count / 10;
		}

		while (1) {

			printf(">>> 目前第 %d 页，总共有 %d 页，输入 0 退出：", page + 1, total_page);

			int input_page;
			scanf("%d", &input_page);

			if (input_page == 0) return OK;

			if (input_page > total_page || input_page < 0) {
				printf("页码不存在，请重试\n");
				continue;
			}

			// page 总比 input_page 少一页
			page = input_page - 1;

			// 输出分页
			printf("==============================================\n");

			for (int i = page * 10; i < page * 10 + 10 && i < Contacts.count; i++) {
				_display_contact(i, Contacts.persons[i]);
			}


		}
	} else {
		// index 是否有效果
		if (index >= 0 || index < Contacts.count) {
			printf("==============================================\n");
			_display_contact(index, Contacts.persons[index]);
			return OK;
		} else {
			return ERROR;
		}
	}
}


// 在 contacts 中，模糊查找姓名
// 请输入需要查找的姓名
// for i in range(contact_count)
// contact.name 简单的便利查找
Status search(char keyword[]) {
	/*
	 存在返回 0
	 不存在返回 1
	*/
	int found = 0;
	for (int i = 0; i < Contacts.count; i++) {
		if (strstr(Contacts.persons[i].name, keyword) != NULL) {
			display(i);
			found = 1;
		}
	}
	return !found;
}

// 进入修改操作
Status edit(int index) {
	char a[200], b[200];
	printf("您可以修改：姓名 / 单位 / 固定电话 / 移动手机 / 分类 / 邮箱 / qq / 住址\n\n");
	printf("ps.其中分类仅可修改为：家人 / 朋友 / 同事 / 同学 / 其他\n\n");
	printf("您需要修改：\n>> ");
	scanf("%s", a);  fflush(stdin);
	printf("为\n>> ");
	gets(b);
	if (strcmp(a, "姓名") == 0) {
		strcpy(Contacts.persons[index].name, b);
	} else if (strcmp(a, "单位") == 0) {
		strcpy(Contacts.persons[index].organization, b);
	} else if (strcmp(a, "固定电话") == 0) {
		strcpy(Contacts.persons[index].landline, b);
	} else if (strcmp(a, "移动手机") == 0) {
		strcpy(Contacts.persons[index].mobile, b);
	} else if (strcmp(a, "分类") == 0) {
		if (strcmp(b, "家人") == 0) {
			Contacts.persons[index].category = FAMILY;
		} else if (strcmp(b, "朋友") == 0) {
			Contacts.persons[index].category = FRIEND;
		} else if (strcmp(b, "同事") == 0) {
			Contacts.persons[index].category = COLLEAGUE;
		} else if (strcmp(b, "同学") == 0) {
			Contacts.persons[index].category = CLASSMATE;
		} else if (strcmp(b, "其他") == 0) {
			Contacts.persons[index].category = OTHER;
		} else {
			printf("输入错误，请重新修改");
			return ERROR;
		}
	} else if (strcmp(a, "邮箱") == 0) {
		strcpy(Contacts.persons[index].email, b);
	} else if (strcmp(a, "qq") == 0) {
		strcpy(Contacts.persons[index].qq, b);
	} else if (strcmp(a, "住址") == 0) {
		strcpy(Contacts.persons[index].address, b);
	} else {
		printf("输入错误，请重新修改");
		return ERROR;
	}
	printf("修改成功，已将编号为 %d（%s）的 %s 修改为 %s", index, Contacts.persons[index].name, a, b);
	return OK;
}
// 进行 。。。 操作
// 有一个菜单，有下面需要修改的选项
// 姓名
// 单位
// 固定电话
// 移动手机
// 分类
// 电子邮箱
// QQ号码
// 住址

// 进入增加操作
Status add() {
	Contact new_person;
	printf("请输入新联系人的信息：\n");
	printf("姓名：");
	gets(new_person.name);
	printf("单位：");
	gets(new_person.organization);
	printf("固定电话和移动手机（空格隔开）：");
	scanf("%s %s", new_person.landline, new_person.mobile); fflush(stdin);
	printf("分类（家人/朋友/同事/同学/其他）：");
	char category_str[20];
	scanf("%s", category_str);  fflush(stdin);
	if (strcmp(category_str, "家人") == 0) {
		new_person.category = FAMILY;
	} else if (strcmp(category_str, "朋友") == 0) {
		new_person.category = FRIEND;
	} else if (strcmp(category_str, "同事") == 0) {
		new_person.category = COLLEAGUE;
	} else if (strcmp(category_str, "同学") == 0) {
		new_person.category = CLASSMATE;
	} else if (strcmp(category_str, "其他") == 0) {
		new_person.category = OTHER;
	} else {
		printf("无此分类\n");
		return ERROR;
	}
	printf("电子邮箱：");
	scanf("%s", new_person.email);  fflush(stdin);
	printf("QQ号码：");
	scanf("%s", new_person.qq); fflush(stdin);
	printf("住址：");
	gets(new_person.address);

	Contacts.persons[Contacts.count++] = new_person;
	printf("联系人添加成功！联系人 ID 为：%d\n", Contacts.count - 1);
	return OK;

}


// 修改 contacts 的所有元素前移 contact_count 减一
Status del(int index) {
	int a, i;
	i = index;
	a = i;
	if (i < 0 || i >= Contacts.count) {
		printf("没有该联系人，无法删除\n");
		return ERROR;
	} else {
		for (; i < Contacts.count; i++) {
			Contacts.persons[i] = Contacts.persons[i + 1];
		}
		Contacts.count -= 1;
		printf("成功删除编号为 %d 的联系人\n", a);
		return OK;
	}
}


int utf8_strcmp(const char *a, const char *b) {
	return strcmp(a, b); // 直接比较UTF-8字节序列
}

// 对联系人按姓名进行排序
Status sort_contacts() {
	int i, j;
	Contact temp;
	for (i = 0; i < Contacts.count - 1; i++) {
		for (j = 0; j < Contacts.count - i - 1; j++) {
			if (utf8_strcmp(Contacts.persons[j].name, Contacts.persons[j + 1].name) > 0) {
				temp = Contacts.persons[j];
				Contacts.persons[j] = Contacts.persons[j + 1];
				Contacts.persons[j + 1] = temp;
			}
		}
	}
	printf("联系人已按姓名排序\n");
	return OK;
}

// 统计遍历 contacts 的 category
// 建立 5 个变量 或者 一个数组 5 个项
// +1 统计
Status statistics() {
	int jr = 0, py = 0, ts = 0, tx = 0, qt = 0;
	for (int i = 0; i < Contacts.count; i++) {
		if (Contacts.persons[i].category == FAMILY)
			jr += 1;
		else if (Contacts.persons[i].category == FRIEND)
			py += 1;
		else if (Contacts.persons[i].category == COLLEAGUE)
			ts += 1;
		else if (Contacts.persons[i].category == CLASSMATE)
			tx += 1;
		else
			qt += 1;
	}
	printf("统计信息如下：\n");
	printf("家人有 %d 人\n", jr);
	printf("朋友有 %d 人\n", py);
	printf("同事有 %d 人\n", ts);
	printf("同学有 %d 人\n", tx);
	printf("其他有 %d 人\n", qt);
	printf("一共有 %d 人\n", Contacts.count);
}


// 导出：符合格式：
// 张三,嘉兴南湖学院,114514,114514,3,11@qq.com,123,韭菜鸡蛋\n
// 写到 contacts.csv
Status write() {
	FILE *file = fopen("contacts.csv", "w");
	if (!file) {
		printf("Error: 不能打开文件！\n");
		return ERROR;
	}

	for (int i = 0; i < Contacts.count; i++) {
		Contact *person = &Contacts.persons[i];
		fprintf(file, "%s,%s,%s,%s,%d,%s,%s,%s\n",
		        person->name,
		        person->organization,
		        person->landline,
		        person->mobile,
		        person->category,
		        person->email,
		        person->qq,
		        person->address);
	}

	fclose(file);
	printf("成功导出 %d 个联系人到 contacts.csv\n", Contacts.count);
	return OK;
}

// 输出帮助
void help() {
	printf( "指令帮助（方括号内为参数，加星号为必填参数）：\n"
	        "● display [ID] - 翻页查看所有联系人，如果提供 ID 则查询该联系人\n"
	        "● search [*keywords] - 模糊查找联系人并输出\n"
	        "● edit [*ID] - 修改该 ID 联系人的信息\n"
	        "● add - 添加新联系人\n"
	        "● del [*ID] - 删除该 ID 联系人\n"
	        "● sort - 整理通讯录，对所有联系人排序\n"
	        "● stat - 分析通讯簿中联系人组成\n"
	        "● save - 保存联系人\n"
			"● help - 显示帮助\n"
			"● exit - 退出程序\n");
}


int main() {
	// 开始先判断一下联系人文件是否存在，如果存在就读取联系人
	if (file_exists("contacts.csv")) {
		read();
	}

	printf( "=============================================================================\n"
	        "                            ★ 个人通讯录管理系统 ★                         \n"
	        "                    守正创新，求实奋进，让科技服务于每一个人                 \n"
	        "                  嘉兴南湖学院 AI241 C语言实训课 第一小组作品                \n"
	        "          Developers: Zhang Yishang, Shen Yizhou, Chen ZiHao, Wang Ye        \n"
	        "=============================================================================\n"

	        "   ('-.      _ .-') _    _ .-') _    _  .-')      ('-.     .-')      .-')    \n"
	        "  ( OO ).-. ( (  OO) )  ( (  OO) )  ( \\( -O )   _(  OO)   ( OO ).   ( OO ).  \n"
	        "  / . --. /  \\     .'_   \\     .'_   ,------.  (,------. (_)---\\_) (_)---\\_) \n"
	        "  | \\-.  \\   ,`'--..._)  ,`'--..._)  |   /`. '  |  .---' /    _ |  /    _ |  \n"
	        ".-'-'  |  |  |  |  \\  '  |  |  \\  '  |  /  | |  |  |     \\  :` `.  \\  :` `.  \n"
	        " \\| |_.'  |  |  |   ' |  |  |   ' |  |  |_.' | (|  '--.   '..`''.)  '..`''.) \n"
	        "  |  .-.  |  |  |   / :  |  |   / :  |  .  '.'  |  .--'  .-._)   \\ .-._)   \\ \n"
	        "  |  | |  |  |  '--'  /  |  '--'  /  |  |\\  \\   |  `---. \\       / \\       / \n"
	        "  `--' `--'  `-------'   `-------'   `--' '--'  `------'  `-----'   `-----   \n"
	        "=============================================================================\n"
	      );

	// 进入功能主循环
	printf( "★ Info: 目前通讯录中有 %d 个联系人，您可以选择功能进行添加或删除。\n\n", Contacts.count );
	help();
	
	
	char input[256];
	while (1) {
		fflush(stdin);
		printf("\n请输入指令> ");
		if (fgets(input, sizeof(input), stdin) == NULL) break;
		input[strcspn(input, "\n")] = 0; // 去除换行符

		// 分割命令和参数
		char *cmd = input;
		char *args = NULL;
		char *space = strchr(input, ' ');
		if (space) {
			*space = '\0';
			args = space + 1;
		}

		if (strcmp(cmd, "display") == 0) {
			if (!args) display(-1);
			else {
				char *end;
				long idx = strtol(args, &end, 10);
				if (*end || idx < 0 || idx >= Contacts.count)
					printf("无效联系人ID！\n");
				else
					display((int)idx);
			}
		} else if (strcmp(cmd, "search") == 0) {
			if (!args) printf("请输入搜索关键词！\n");
			else {
				printf("搜索到如下结果：\n");
				if (search(args)) {
					printf("没有找到符合要求的联系人。\n");
				}
			} 
		} else if (strcmp(cmd, "edit") == 0) {
			if (!args) printf("需要指定联系人ID！\n");
			else {
				char *end;
				long idx = strtol(args, &end, 10);
				if (*end || idx < 0 || idx >= Contacts.count)
					printf("无效联系人ID！\n");
				else
					edit((int)idx);
			}
		} else if (strcmp(cmd, "add") == 0) add();
		else if (strcmp(cmd, "del") == 0) {
			if (!args) printf("需要指定联系人ID！\n");
			else {
				char *end;
				long idx = strtol(args, &end, 10);
				if (*end || idx < 0 || idx >= Contacts.count)
					printf("无效联系人ID！\n");
				else
					del((int)idx);
			}
		} else if (strcmp(cmd, "sort") == 0) sort_contacts();
		else if (strcmp(cmd, "stat") == 0) statistics();
		else if (strcmp(cmd, "save") == 0) write();
		else if (strcmp(cmd, "help") == 0) help();
		else if (strcmp(cmd, "exit") == 0) {
			write();
			printf("感谢使用，再见！\n");
			break;
		} else printf("未知指令，输入help查看帮助\n");
	}
	
	return 0;
}